home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Environments / PowerFantasm™ 4.19a / PowerFantasm™ / F4_EXAMPLES / game / **README**Game next >
Text File  |  1997-02-10  |  13KB  |  246 lines

  1. In the unregistered version of PowerFantasm, source code for this is not included for
  2. two reasons. 
  3. 1. The demo can't assemble it because of a code size limitation, and 
  4. 2. We have to keep the unregistered version size down to a minimum.
  5.  
  6. You may obtain the source code from our WWW pages - http://www.tau.it/lightsoft
  7.  
  8. ----------------------------------------------------------------------------------
  9.  
  10. PF410 was to be released with no new example code. Then a few days back I was given
  11. a challenge. These are the notes from that challenge. 
  12.  
  13. The challenge was to write the basics of a native sprite based game in 24 hours and this 
  14. is the result. 
  15.  
  16. It starts off 7 hours in, as the first seven hours were writing the basic screen splat 
  17. and routines.
  18.  
  19. Big note for splats -  a read or write
  20. to memory with the floating double instructions will cause a memory exception on
  21. 604's, so make sure you are 8 aligned if using these instructions - see the screen
  22. splat and init code for usage...
  23.  
  24. Another note - in this particular example the MMU was letting me get away with passing a 
  25. really bad address to clear_icl8 until I switched VM on - then the machine crashed.
  26. Be very sure to check both with VM on and off as the MMU behaves differently.
  27.  
  28. -------------------------------------------------------------------------------
  29.  
  30. Ok, 7 hours in and I'm working on the player bullets. Have defined four arrays,
  31. each 10 halfs each. x,y,old_x and old_y for each bullet.
  32. The theory is that when we press the mouse button, the y_array is searched for an empty slot
  33.  - that is any slot containing -1. We store x and y coords of the left gun in these arrays.
  34. Calc_bullets steps through the y array looking for entries that are not -1. These are
  35. valid y coords. The y coord is decremented by 10, then checked against 20.
  36. If greater than 20 then do the next bullet slot. If less than 20 then delete the bullet 
  37. and set this y_coord to -1.
  38.  
  39. This set up limits the number of player bullets on screen to 10 (in the equates file). 
  40. Because the gun will
  41. auto repeat, after firing a bullet we set a delay so that the fire routine isn't checked
  42. again until this counter runs out.
  43.  
  44. Next, get it to fire two bullets at the same time - one from each gun. I think that this is
  45. simply a case of altering the coords when we fire and saving it in the next x and y
  46. slot.
  47.  
  48. Well, aparently not! The first bullet comes out of the left hand gun as it should, but the
  49. other comes out of the bottom of the screen displaced left by some 200 pixels! Eh?
  50.  
  51. Turns out to just have been bad maths - however, I did think it be a good idea to have the 
  52. guns alternate, left/right so reduced the fire delay to 4 cycles and introduced a variable - turret?
  53. which makes the routine alternate left/right guns (which will make for better sound!)
  54.  
  55. Ok, now I've added an equates file to the project, and redefined the number of bullets to 
  56. 20. I noticed that the bullets routines were not working right, in that after the max number
  57. had been fired, the guns would not fire until the last bullet cleared the screen. This 
  58. was traced to the compare to -1 conditional branch in find_slot being the wrong way
  59. round - should've been a beq!
  60.  
  61. Noticed that the players ship is slightly blanking out the bullets in the first frame of
  62. bullet movement on the right hand size. This is because I'm simply clearing the whole
  63. 32 bits width befoire drawing a bullet, when in fact I only need to clear the bullet width
  64. which is three. So, by moving the bullet over to the far left of the icl8 and
  65. changing clear and print icl8_little, I'll gain speed and remove the visual interference.
  66.  
  67. Ok, so modified both clear and print - what I did to make sure it was working properly was
  68. change the background colour of the bullet from zero to 1, so I could see how much was being 
  69. printed. Also the sprite has been reduced to three pixels wide as it looks better, and
  70. the print adjusted accordingly
  71.  
  72. Ok, it's midnight, which is 8 hours in. The players bullets are now finished.
  73.  
  74. Now, onto the nasties. I have to decide on the maximum on screen any any one time.
  75.  
  76. For now I'll say 20. Each monster is one single icl8, so we need 4 arrays again,
  77. x,y,old_x and old_y - each sized to number_monsters.
  78.  
  79. We need three routines. One to init the positions. One to calculate positions, and one to 
  80. draw the little blighters (erasing the old ones first obviously) It's important, as the 
  81. monsters can cross each other, to erase all of them in one go.
  82.  
  83. To be honest, at this stage, I'll be happy just to draw them and get a frame timing, then
  84. adjust the maximum number accordingly.
  85.  
  86. So, first to init monsters. As this is a simple game, for now I'm just using one monster
  87. shape - icl8 140. Read into monster_sprite1
  88. I'm going to use fixed data, in init to initialise the arrays. Because i~ have to 
  89. type in the data, for now I've set the number of monsters to 5. The init routine
  90. simply copies the x and y coords out of the data to the x,y,x_old and y_old arrays.
  91.  
  92. Get some coffee.
  93.  
  94. Ok, it 0025 now, and the init routine is done. Next draw_monsters. First this has to
  95. go through the arrays and call blank_icl8 which will erase all the old monsters.
  96. Then again, go through a loop, anloy this time call draw_icl8 which is already written.
  97.  
  98. Ok, I've written the clear and splat routines for the monsters, now before running them
  99. I need to get a timing for 1000 frames then I can see how much the monster print has slowed
  100. it down.
  101. Without the stars or monsters I get 532 ticks, which is 1000/(532/60) 113 frames/sec.
  102.  
  103. Now switch on the monster print...and...589 ticks - thats with 5 monsters=101 fps.
  104. However, what the monster print routine is printing isn't how it looks in Resedit!
  105. So, hello Macsbug...As it turns out, didn't need Macsbug, it's just that splat_icl8
  106. doens't preserve the pointer to the data, so I just saved it in r25 and all is ok. 
  107. BUT I did notice that the splat_icl8_three_vert routine seems to be splatting 64
  108. rather than 32 bytes horizontally...yup, it was the clear routines rather than the 
  109. splat routines - a hangover from the integer unit word splat.
  110.  
  111. SO, finally, I can get a time with the stars and five monsters - 102 fps.
  112. Now lets bung up the number of monsters to 10 - 93 fps, now lets see if I cant get
  113. that up by 1. Apparently not at this stage. OK. Well it's 0100, so thats 9 hours. 
  114.  
  115. Next up is the monster movement routines. As I only have 15 hours left, it's has to be 
  116. simple this time. I think first I'll write a default controller which just flaots
  117. the monsters about - if they hit a side, then reverse the delta in that direction.
  118.  
  119. So, we need two more arrays - mdelta_x and mdelta_y (as bytes) BUT at this time, I know 
  120. that I'm going to use more than one control mechanism, so I'll define another array
  121. (of bytes) - mcontrol.
  122.  
  123. In the init phase, we generate random delta values for the monsters - minimum of 1 and
  124. maximum of 3, but this isn't called in the normal init, as we want to call this routine
  125. to start a new stage, so I'll define a new source file - wave_init.s
  126. Ok, written a routine -wave_init which sets up the arrays with random delta values,
  127. in the range of 0-3. This means it's possible to get monsters that wont move, but I'll
  128. sort that out later. (add 1 if zero etc)
  129.  
  130. Next routine is move_monsters. This gets each monsters x,y and delta_x,y.
  131. Checks the coords of each monster, and if out of bounds, reverses the relevant
  132. delta. Took twenty minutes to write and now the game crashes brilliantly!
  133.  
  134. Hmm, ok, this was a classic mistake. The x and y's are half sized arrays, the deltas
  135. are bytes - I was simply adding just 1 to the x and y array pointers, so the first x was
  136. correct, all the rest were rubbish! Now, all the monsters are simply moving to the
  137. corners and staying there, which would really make the game too easy :-)
  138.  
  139. Coffee...
  140.  
  141. Ok, two faults. Firstly I wasn't saving the delta values back in the array, and
  142. secondly because we are using signed delta values, I needed to extend the sign of
  143. the delta byte! Ok, so it now works! As predicted one of the monsters didn't move
  144. so back into wave init... It turns out that monster #10 is not moving?
  145. Into Macsbug, check out the delta arrays and sure enough, entry 10 is 0?
  146. Bummer - wave_init was stuffing both deltas into the same array! Fixed now and all my
  147. little aliens are moving - hurrah!
  148.  
  149. Lets get a frame rate...94fps.
  150.  
  151. Phew. Right is 1:45, which means this is nearly 10 hours in so far.
  152.  
  153. Next up is player bullets hitting the nasty aliens. Now when an alien is hit, all we
  154. have to do is set its y coord to -1 and modify the routines to ignore such a beasty.
  155.  
  156. First though, we need to go back into calc_bullets to detect a hit. In calc_b_loop
  157. we subtract 10 from the bullets y coord. Given this coord we can call check_monster_hit 
  158. which compares the bullets x and y coords with all active aliens. If the bullet is in one
  159. of the aliens rectangles, it returns the monster number, otherwise zero. This is less
  160. tidy than calling a routine from the main loop, but is faster as we have the bullets coords
  161. and number handy.
  162.  
  163. Time for some music, as this will take a while to write - eh? This disk is unreadable by...
  164. Oh yes, best put the foreign file access thingies in...
  165.  
  166. Ok, routines written, and it don't crash, but it isn't working, so I;m going to reduce the 
  167. number of monsters to 1 so it's easier to debug.
  168.  
  169. Doddle - just a mix up over x and y's. In check_monster_hit, if it is, all we do is 
  170. bung a -1 in the monsters y coord and it goes away. Right bung the number of monsters
  171. back upto 20 and give it a blast (ah the joys of equate files).
  172.  
  173.  
  174. Ok, something very weird is happening. As I shoot monsters, then game gets slower and 
  175. slower? I'm supposed to be equalising now! Yup, I had forgotten to modify the drawing routines
  176. to take account of y values with -1. The reason it was slowing down is because it was
  177. drawing off screen, which is probably not lined up on an 8 byte boundary! Anyway, I've 
  178. added a down counter that decrements when a monster is killed, and when zero sets the 
  179. global flag end_of_wave to tell the main loop to stop.
  180.  
  181. Phew. 0300 and looking good. Right lets get a frame check with 10 monsters - 92.7 fps.
  182. And with 20..remembering to make some more entries in the init data...80 fps. So we're
  183. still good for a few number of aliens.
  184.  
  185. Now, next we come to the aliens dropping bombs on us - we need some rules first.
  186. One alien - one bomb. Now because these monsters have to decide when to drop a bomb,
  187. we do not want to be calling get_random for every monster in every loop - far too slow.
  188. What I'll do is define two more arrays - monster_bomb_counter and monster_bomb_counter_reset.
  189. These are set up in wave_init and when the counter reaches zero, the monster tries
  190. to drop a bomb. If it has no active bomb then it can drop one. We reset the counter
  191. from the reset array. This way, all we have to do is decrement a counter - far faster.
  192.  
  193. An inactive bomb is indicated by -1 in the monster_bomb_y array.
  194.  
  195. Right, lets do it...First off, wave_init to set up the counter arrays. Ok minor change,
  196. another array - monster_bomb_deltas - the y delta for the bomb - set in init_wave.
  197. Ok, after an hour and half of mucking about tweaking things, that now works. Main problem 
  198. was making sure dead aliens don't drop bombs!
  199.  
  200. Next is the player/alien bomb collision detection. This fits naturally into the move monster
  201. nomb routine at label check_player.
  202.  
  203. Finally is alien/player collision - again same stuff - draw a rectangle and compare, but
  204. this time we have to check all four corners of the monster against the players rectangle.
  205. Done in draw_m_loop.
  206.  
  207. OK, its 0630 - fps check.
  208. 20 monsters - 80 frames/sec
  209. 10 monsters - 93 fps. Dont seem to have wasted any time on the collision detection. Good.
  210.  
  211. Now it's time to add some basic levels - simple:
  212. Level 1=5 monsters
  213. level 2=10
  214. level 3=15
  215. level 4=20
  216. Then bonus level which ends scheme 1.
  217. ...
  218. So some four hours later, I've added in basic sound, some very simple level increments
  219. and got our artist to draw some simple sprites - the end result you can see for yourself!
  220.  
  221. ----------------------------------------------------
  222.  
  223. Endispiece...
  224.  
  225. Well, all that was done about three or four days ago. I have now recovered :-)
  226.  
  227. I'd like to thank Rob, Claire and James for support. 
  228. Not only for this little demo, but for all the stirling work they do otherwise.
  229.  
  230.  
  231.  
  232. Please note that:
  233. 1.  All code contained in PF410 example game is copyright Lightsoft 96.
  234.  
  235. 2. Some of the clear and splat routines can be optimised further - for example 
  236. you may find the odd li instruction in a loop, which can move outside etc.
  237.  
  238. Feel free to use the ideas contained herein, but please do not simply push this work out
  239. as your own. If you use portions of the game code in your own games, then you are
  240. legally obliged to state that portions of the code are copyright Lightsoft.
  241.  
  242. Thankyou.
  243.  
  244.  
  245. -----------------------------------
  246.